/*************************************************************************
	> File Name: show_jpg.c
	>Author :卢孙远(Simon)
	> company: GDOU
	> Mail: lsy476941913@live.com
	> Created Time: 2017年03月5日 星期四 20时36分17秒
 ************************************************************************/
#include "show_jpg.h"
void show_someone(char *fb_mem, int id)
{
	static int firsttime = 1;

	int namelen = 16;
	static char *oldfile = NULL;
	static char *newfile = NULL;

	if (firsttime == 1) {
		oldfile = calloc(1, namelen);
		newfile = calloc(1, namelen);

		snprintf(oldfile, namelen, "./jpg/%d.jpg", id);
		snprintf(newfile, namelen, "./jpg/%d.jpg", id);

		printf("[%d]: %s\n", __LINE__, newfile);
		show_in(fb_mem, newfile);

		firsttime = 0;
		return;
	}

	snprintf(newfile, namelen, "./jpg/%d.jpg", id);
	fade_out(fb_mem, oldfile);
	show_in(fb_mem, newfile);

	return;
}

void show_in(char *fb_mem, char *filename)
{
	char *rgb_buf = get_rgb(filename);
	blind_window_in(fb_mem, (stride) rgb_buf);
	free(rgb_buf);
}

void fade_out(char *fb_mem, char *filename)
{
	char *rgb_buf = get_rgb(filename);
	blind_window_out(fb_mem, (stride) rgb_buf);
	free(rgb_buf);
}



// 将jpeg文件的压缩图像数据读出，放到jpg_buffer中去等待解压

unsigned long read_image_from_file(int fd,
	unsigned char *jpg_buffer,
	unsigned long jpg_size)
{
	unsigned long nread = 0;
	unsigned long total = 0;

	while (jpg_size > 0) {
		nread = read(fd, jpg_buffer, jpg_size);
		if (nread == -1) {
			perror("read jpeg-file failed");
			exit(EXIT_SUCCESS);
		}

		jpg_size -= nread;
		jpg_buffer += nread;
		total += nread;
	}
	close(fd);

	return total;
}

char *transfor(unsigned char *rgb_buffer)
{
	char *rgb_buf = calloc(1, 800 * 480 * 4);
	unsigned char *tmp = rgb_buffer + 1;

	int offset[6][3] = {
		{0, 1, 2},
		{0, 2, 1},
		{1, 0, 2},
		{1, 2, 0},
		{2, 0, 1},
		{2, 1, 0},
	};

	int i, j;
	static int n = 0;
	for (i = 0; i < 480; i++) {
		for (j = 0; j < 800; j++) {
			memcpy(rgb_buf + (j + 800 * i)*4 + 0,
				tmp + (j + 800 * i)*3 + offset[2][0], 1);
			memcpy(rgb_buf + (j + 800 * i)*4 + 1,
				tmp + (j + 800 * i)*3 + offset[2][1], 1);
			memcpy(rgb_buf + (j + 800 * i)*4 + 2,
				tmp + (j + 800 * i)*3 + offset[2][2], 1);
		}
	}
	printf("--->> n:%d <<---\n", n);
	n++;
	free(rgb_buffer);
	return rgb_buf;
}

char *get_rgb(char *filename)
{
	// 读取图片文件属性信息
	// 并根据其大小分配内存缓冲区jpg_buffer
	struct stat file_info;
	stat(filename, &file_info);
	int fd = Open(filename, O_RDONLY);

	unsigned char *jpg_buffer;
	jpg_buffer = (unsigned char *) calloc(1, file_info.st_size);
	read_image_from_file(fd, jpg_buffer, file_info.st_size);

	// 声明解压缩结构体，以及错误管理结构体
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;

	// 使用缺省的出错处理来初始化解压缩结构体
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);

	// 配置该cinfo，使其从jpg_buffer中读取jpg_size个字节
	// 这些数据必须是完整的JPEG数据
	jpeg_mem_src(&cinfo, jpg_buffer, file_info.st_size);

	// 读取JPEG文件的头，并判断其格式是否合法
	int ret = jpeg_read_header(&cinfo, true);
	if (ret != 1) {
		fprintf(stderr, "[%d]: jpeg_read_header failed: "
			"%s\n", __LINE__, strerror(errno));
		exit(EXIT_SUCCESS);
	}

	// 开始解压
	jpeg_start_decompress(&cinfo);

	int row_stride = cinfo.output_width * cinfo.output_components;

	// 根据图片的尺寸大小，分配一块相应的内存rgb_buffer
	// 用来存放从jpg_buffer解压出来的图像数据
	unsigned long rgb_size;
	unsigned char *rgb_buffer;
	rgb_size = row_stride * cinfo.output_height;
	rgb_buffer = (unsigned char *) calloc(1, rgb_size);

	// 循环地将图片的每一行读出并解压到rgb_buffer中
	while (cinfo.output_scanline < cinfo.output_height) {
		unsigned char *buffer_array[1];
		buffer_array[0] = rgb_buffer +
			(cinfo.output_scanline) * row_stride;
		jpeg_read_scanlines(&cinfo, buffer_array, 1);
	}

	// 解压完了，将jpeg相关的资源释放掉
	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	free(jpg_buffer);

	return transfor(rgb_buffer);
}



//百叶窗多线程函数

void *__routine(void *p)
{
	struct argument *arg = (struct argument *) p;

	int i;

	if (arg->flag == IN) {
		for (i = HEIGHT / BLIND - 1; i >= 0; i--) {
			memcpy(&(arg->fb_mem)[arg->offset + i][0],
				&(arg->image)[arg->offset + i][0],
				WIDTH * 4);

			usleep(10000);
		}
	}

	if (arg->flag == OUT) {
		for (i = 0; i < HEIGHT / BLIND; i++) {
			memset(&(arg->fb_mem)[arg->offset + i][0], 0, WIDTH * 4);

			usleep(10000);
		}
	}

	pthread_exit(NULL);
}

void __write_lcd(char *fb_mem, unsigned long (*image)[WIDTH], int flag)
{
	int i;
	pthread_t tid[BLIND];
	for (i = 0; i < BLIND; i++) {
		struct argument *arg =
			malloc(sizeof(struct argument));
		arg->fb_mem = (stride) fb_mem;
		arg->image = image;
		arg->offset = i * (HEIGHT / BLIND);
		arg->flag = flag;

		pthread_create(&tid[i], NULL, __routine, (void *) arg);
	}

	for (i = 0; i < BLIND; i++) {
		pthread_join(tid[i], NULL);
	}
}

void blind_window_in(char *fb_mem, unsigned long (*image)[WIDTH])
{
	__write_lcd(fb_mem, image, IN);
}

void blind_window_out(char *fb_mem, unsigned long (*image)[WIDTH])
{
	__write_lcd(fb_mem, image, OUT);
}

void blind_window(char *fb_mem, unsigned long (*image)[WIDTH])
{
	blind_window_in(fb_mem, image);
	blind_window_out(fb_mem, image);
}

